home *** CD-ROM | disk | FTP | other *** search
/ Aminet 48 / Aminet 48 (2002)(GTI - Schatztruhe)[!][Apr 2002].iso / Aminet / text / edit / vim60rt.lha / Vim / vim60 / ftplugin / ada.vim next >
Encoding:
Text File  |  2001-09-18  |  5.9 KB  |  206 lines

  1. " Vim Ada plugin file
  2. " Language:    Ada
  3. " Maintainer:    Neil Bird <neil@fnxweb.com>
  4. " Last Change:    2001 September 18
  5. " Version:    $Id: ada.vim,v 1.2 2001/09/18 07:57:04 nabird Exp $
  6.  
  7. " Perform Ada specific completion & tagging.
  8. "
  9. " Provides mapping overrides for tag jumping that figure out the current
  10. " Ada object and tag jump to that, not the 'simple' vim word.
  11. " Similarly allows <Ctrl-N> matching of full-length ada entities from tags.
  12. " Exports 'AdaWord()' function to return full name of Ada entity under the
  13. " cursor( or at given line/column), stripping whitespace/newlines as necessary.
  14.  
  15.  
  16. " Only do this when not done yet for this buffer
  17. if exists("b:did_ftplugin")
  18.   finish
  19. endif
  20.  
  21. " Don't load another plugin for this buffer
  22. let b:did_ftplugin = 1
  23.  
  24. " Temporarily set cpoptions to ensure the script loads OK
  25. let s:cpoptions = &cpoptions
  26. set cpo-=C
  27.  
  28.  
  29. " Make local tag mappings for this buffer (if not already set)
  30. if mapcheck('<C-]>','n') == ''
  31.   nnoremap <unique> <buffer> <C-]>    :call JumpToTag_ada('')<cr>
  32. endif
  33. if mapcheck('g<C-]>','n') == ''
  34.   nnoremap <unique> <buffer> g<C-]>   :call JumpToTag_ada('','stj')<cr>
  35. endif
  36.  
  37. if mapcheck('<C-N>','i') == ''
  38.   inoremap <unique> <buffer> <C-N> <C-R>=<SID>AdaCompletion("\<lt>C-N>")<cr>
  39. endif
  40. if mapcheck('<C-P>','i') == ''
  41.   inoremap <unique> <buffer> <C-P> <C-R>=<SID>AdaCompletion("\<lt>C-P>")<cr>
  42. endif
  43. if mapcheck('<C-X><C-]>','i') == ''
  44.   inoremap <unique> <buffer> <C-X><C-]> <C-R>=<SID>AdaCompletion("\<lt>C-X>\<lt>C-]>")<cr>
  45. endif
  46.  
  47.  
  48. " Only do this when not done yet for this buffer & matchit is used
  49. if ! exists("b:match_words")  &&  exists("loaded_matchit")
  50.   " The following lines enable the macros/matchit.vim plugin for
  51.   " Ada-specific extended matching with the % key.
  52.   let s:notend = '\%(\<end\s\+\)\@<!'
  53.   let b:match_words=
  54.   \ s:notend . '\<if\>:\<elsif\>:\<else\>:\<end\>\s\+\<if\>,' .
  55.   \ s:notend . '\<case\>:\<when\>:\<end\>\s\+\<case\>,' .
  56.   \ '\%(\<while\>.*\|\<for\>.*\|'.s:notend.'\)\<loop\>:\<end\>\s\+\<loop\>,' .
  57.   \ '\%(\<do\>\|\<begin\>\):\<exception\>:\<end\>\s*\%($\|[;A-Z]\),' .
  58.   \ s:notend . '\<record\>:\<end\>\s\+\<record\>'
  59. endif
  60.  
  61.  
  62. " Prevent re-load of functions
  63. if exists('s:id')
  64.   finish
  65. endif
  66.  
  67. " Get this script's unique id
  68. map <script> <SID>?? <SID>??
  69. let s:id = substitute( maparg('<SID>??'), '^<SNR>\(.*\)_??$', '\1', '' )
  70. unmap <script> <SID>??
  71.  
  72.  
  73. " Extract current Ada word across multiple lines
  74. " AdaWord( [line, column] )\
  75. let s:AdaWordRegex = '\a\w*\(\_s*\.\_s*\a\w*\)*'
  76. let s:AdaComment   = "\\v^(\"[^\"]*\"|'.'|[^\"']){-}\\zs\\s*--.*"
  77.  
  78. function! AdaWord(...)
  79.   if a:0 > 1
  80.     let linenr = a:1
  81.     let colnr  = a:2 - 1
  82.   else
  83.     let linenr = line('.')
  84.     let colnr  = col('.') - 1
  85.   endif
  86.   let line = substitute( getline(linenr), s:AdaComment, '', '' )
  87.   " Cope with tag searching for items in comments; if we are, don't loop
  88.   " backards looking for previous lines
  89.   if colnr > strlen(line)
  90.     " We were in a comment
  91.     let line = getline(linenr)
  92.     let search_prev_lines = 0
  93.   else
  94.     let search_prev_lines = 1
  95.   endif
  96.  
  97.   " Go backwards until we find a match (Ada ID) that *doesn't* include our
  98.   " location - i.e., the previous ID. This is because the current 'correct'
  99.   " match will toggle matching/not matching as we traverse characters
  100.   " backwards. Thus, we have to find the previous unrelated match, exclude
  101.   " it, then use the next full match (ours).
  102.   " Remember to convert vim column 'colnr' [1..n] to string offset [0..(n-1)]
  103.   " ... but start, here, one after the required char.
  104.   let newcol = colnr + 1
  105.   while 1
  106.     let newcol = newcol - 1
  107.     if newcol < 0
  108.       " Have to include previous line from file
  109.       let linenr = linenr - 1
  110.       if linenr < 1  ||  !search_prev_lines
  111.         " Start of file or matching in a comment
  112.         let linenr = 1
  113.         let newcol = 0
  114.         let ourmatch = match( line, s:AdaWordRegex )
  115.         break
  116.       endif
  117.       " Get previous line, and prepend it to our search string
  118.       let newline = substitute( getline(linenr), s:AdaComment, '', '' )
  119.       let newcol  = strlen(newline) - 1
  120.       let colnr   = colnr + newcol
  121.       let line    = newline . line
  122.     endif
  123.     " Check to see if this is a match excluding 'us'
  124.     let mend = newcol + matchend( strpart(line,newcol), s:AdaWordRegex ) - 1
  125.     if mend >= newcol  &&  mend < colnr
  126.       " Yes
  127.       let ourmatch = mend+1 + match( strpart(line,mend+1), s:AdaWordRegex )
  128.       break
  129.     endif
  130.   endwhile
  131.  
  132.   " Got anything?
  133.   if ourmatch < 0
  134.     return ''
  135.   else
  136.     let line = strpart( line, ourmatch)
  137.   endif
  138.  
  139.   " Now simply add further lines until the match gets no bigger
  140.   let matchstr = matchstr( line, s:AdaWordRegex )
  141.   let lastline  = line('$')
  142.   let linenr    = line('.') + 1
  143.   while linenr <= lastline
  144.     let lastmatch = matchstr
  145.     let line = line . substitute( getline(linenr), s:AdaComment, '', '' )
  146.     let matchstr = matchstr( line, s:AdaWordRegex )
  147.     if matchstr == lastmatch
  148.       break
  149.     endif
  150.   endwhile
  151.  
  152.   " Strip whitespace & return
  153.   return substitute( matchstr, '\s\+', '', 'g' )
  154. endfunction
  155.  
  156.  
  157. " Word tag - include '.' and if Ada make uppercase
  158. " Name allows a common JumpToTag() to look for an ft specific JumpToTag_ft().
  159. function! JumpToTag_ada(word,...)
  160.   if a:word == ''
  161.     " Get current word
  162.     let word = AdaWord()
  163.     if word == ''
  164.       return
  165.     endif
  166.   else
  167.     let word = a:word
  168.   endif
  169.   if a:0 > 0
  170.     let mode = a:1
  171.   else
  172.     let mode = 'tj'
  173.   endif
  174.  
  175.   let v:errmsg = ''
  176.   execute 'silent!' mode word
  177.   if v:errmsg != ''
  178.     if v:errmsg =~ '^E426:'  " Tag not found
  179.       let ignorecase = &ignorecase
  180.       set ignorecase
  181.       execute mode word
  182.       let &ignorecase = ignorecase
  183.     else
  184.       " Repeat to give error
  185.       execute mode word
  186.     endif
  187.   endif
  188. endfunction
  189.  
  190.  
  191. " word completion (^N/^R/^X^]) - force '.' inclusion
  192. function! s:AdaCompletion(cmd)
  193.   set iskeyword+=46
  194.   return a:cmd . "\<C-R>=<SNR>" . s:id . "_AdaCompletionEnd()\<CR>"
  195. endfunction
  196. function! s:AdaCompletionEnd()
  197.   set iskeyword-=46
  198.   return ''
  199. endfunction
  200.  
  201. " Reset cpoptions
  202. let &cpoptions = s:cpoptions
  203. unlet s:cpoptions
  204.  
  205. " vim: sts=2 sw=2 :
  206.